﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using AKMII.DMRA.Common;

using MapPoint;
using System.Diagnostics;
using ACRODISTXLib;
using System.IO;

namespace AKMII.DMRA.Business.Service
{
    public class MappointService
    {
        Application objApp;
        Route objRoute;
        Map objMap;

        public MappointService()
        {
            objApp = new Application();
            objApp.ActivePrinter = "Adobe PDF";
            objMap = objApp.ActiveMap;
            objRoute = objMap.ActiveRoute;
            objApp.Visible = true;
            objApp.UserControl = true;
            objMap.Parent.PaneState = GeoPaneState.geoPaneRoutePlanner;
        }

        public List<Lead> CalculateRoute(List<Lead> leads)
        {
            List<Lead> result = new List<Lead>();

            if (leads != null && leads.Count > 0)
            {
                try
                {
                    int seq = 1;
                    List<Lead> leadList = leads;
                    foreach (Lead lead in leadList)
                    {
                        //Logger.Info(string.Format("Lead {0}/{1}/{2}/{3}", lead.Longitude, lead.Latitude, lead.StreetAddress, lead.Id));
                        lead.LeadId = seq;

                        objRoute.Waypoints.Add(objApp.ActiveMap.GetLocation(double.Parse(lead.Latitude),
                            double.Parse(lead.Longitude), 100), string.Format("{0};{1};{2};{3};ID({4})",
                            lead.FirstName + " " + lead.LastName, lead.StreetAddress, lead.Telephone, lead.SubSequenceNumber, lead.LeadId));

                        seq++;
                    }
                        
                    if (objRoute.Waypoints.Count > 1)
                    {
                        objRoute.Waypoints.Optimize();
                    }

                    foreach (Waypoint point in objRoute.Waypoints)
                    {
                        string symbolString = "ID(";
                        string locationString = point.Name.Substring(point.Name.IndexOf(symbolString) + symbolString.Length).Replace(")", string.Empty);
                        result.AddRange(leadList.Where(c => c.LeadId == int.Parse(locationString)));
                        leadList.RemoveAll(c => c.LeadId == int.Parse(locationString));
                    }

                    objRoute.Clear();
                }
                catch (Exception ex)
                {
                    Logger.Info("Exception in calculate direction order", ex);
                    Logger.Error("Exception in calculate direction order", ex);
                    result = leads;
                }
                finally
                {
                    if (objRoute != null)
                    {
                        objRoute.Clear();
                    }
                }
            }

            return result;
        }

        public void GenerateOverviewMap(string path, List<Lead> leads)
        {
            if (leads != null && leads.Count > 0)
            {
                try
                {
                    Logger.Info("Generate overview map at " + path);

                    foreach (Lead lead in leads)
                    {
                        //Logger.Info(string.Format("Lead {0}/{1}/{2}/{3} {4}", lead.Longitude, lead.Latitude, lead.StreetAddress, lead.FirstName, lead.LastName));
                        if (lead.Longitude != "0.0000" && lead.Latitude != "0.0000")
                        {
                            objRoute.Waypoints.Add(objApp.ActiveMap.GetLocation(double.Parse(lead.Latitude),
                                double.Parse(lead.Longitude), 100), string.Format("{0},{1},{2},{3}",
                                lead.FirstName + " " + lead.LastName, lead.StreetAddress, lead.Telephone, lead.LeadType + lead.SubSequenceNumber));
                        }
                    }

                    if (objRoute.Waypoints.Count > 1)
                    {
                        objRoute.Calculate();

                        objApp.ActiveMap.PrintOut(path.Replace(".pdf", ".ps"), string.Format("Assignment {0}({1} miles, {2} minutes)",
                            leads[0].UserId, objRoute.Distance.ToString("0.0"), Convert.ToInt32(objRoute.DrivingTime * 24 * 60)), 1, GeoPrintArea.geoPrintFullPage, GeoPrintQuality.geoPrintQualityNormal,
                            GeoPrintOrientation.geoPrintAuto, false, true, false, false);
                        Utility.ConvertToPdf(path.Replace(".pdf", ".ps"), path);

                        objRoute.Clear();
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(string.Format("Exception in overview map for ({0}, {1}) ", leads[0].MdNumber, leads[0].LeadBlockCode), ex);
                    foreach (var lead in leads)
                    {
                        Logger.Error(string.Format("Error lead {0}/{1}/{2}/{3} {4}", lead.Longitude, lead.Latitude, lead.StreetAddress, lead.FirstName, lead.LastName));
                    }
                }
                finally
                {
                    objRoute.Clear();
                }
            }
        }

        public void GenerateStripMap(string path, List<Lead> leads)
        {
            if (leads != null && leads.Count > 0)
            {
                try
                {
                    Logger.Info("Generate strip map at " + path);

                    foreach (Lead lead in leads)
                    {
                        if (lead.Longitude != "0.0000" && lead.Latitude != "0.0000")
                        {
                            objRoute.Waypoints.Add(objApp.ActiveMap.GetLocation(double.Parse(lead.Latitude),
                                double.Parse(lead.Longitude), 100), string.Format("{0},{1},{2},{3}",
                                lead.FirstName + " " + lead.LastName, lead.StreetAddress, lead.Telephone, lead.LeadType + lead.SubSequenceNumber));
                        }
                    }

                    if (objRoute.Waypoints.Count > 1)
                    {
                        objRoute.Calculate();

                        objApp.ActiveMap.PrintOut(path.Replace(".pdf", ".ps"), string.Format("Lead Block {0}", leads[0].LeadBlockCode), 1, GeoPrintArea.geoPrintStripMaps, GeoPrintQuality.geoPrintQualityNormal,
                            GeoPrintOrientation.geoPrintAuto, false, true, false, false);
                        Utility.ConvertToPdf(path.Replace(".pdf", ".ps"), path);

                        objRoute.Clear();

                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(string.Format("Exception in strip map for ({0}, {1}) ", leads[0].MdNumber, leads[0].LeadBlockCode), ex);
                    foreach (var lead in leads)
                    {
                        Logger.Error(string.Format("Error lead {0}/{1}/{2}/{3} {4}", lead.Longitude, lead.Latitude, lead.StreetAddress, lead.FirstName, lead.LastName));
                    }
                }
                finally
                {
                    objRoute.Clear();
                }
            }
        }

        public void Close()
        {
            objApp.ActiveMap.Saved = true;
            objApp.Quit();
            objApp = null;
        }
    }
}
